using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Text;

namespace SumerCoreDevOps.Infrastructure.Libraries;

/// <summary>
/// NuGet 操作库
/// </summary>
public class NuGetLibrary
{
    private readonly ILogger<NuGetLibrary> _logger;

    public NuGetLibrary(ILogger<NuGetLibrary> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// 推送包到 NuGet 仓库
    /// </summary>
    public async Task<bool> PushPackageAsync(
        string packagePath,
        string source,
        string apiKey)
    {
        try
        {
            _logger.LogInformation("开始推送 NuGet 包: {Package} 到 {Source}", packagePath, source);

            if (!File.Exists(packagePath))
            {
                _logger.LogError("包文件不存在: {Path}", packagePath);
                return false;
            }

            var arguments = $"push \"{packagePath}\" -Source \"{source}\" -ApiKey {apiKey}";

            var result = await ExecuteNuGetCommandAsync(arguments);

            if (result.ExitCode == 0)
            {
                _logger.LogInformation("NuGet 包推送成功");
                return true;
            }
            else
            {
                _logger.LogError("NuGet 包推送失败: {Output}", result.Output);
                return false;
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "推送 NuGet 包失败");
            return false;
        }
    }

    /// <summary>
    /// 打包项目
    /// </summary>
    public async Task<(bool Success, string? PackagePath)> PackAsync(
        string projectPath,
        string outputDirectory,
        string? version = null,
        Dictionary<string, string>? properties = null)
    {
        try
        {
            _logger.LogInformation("开始打包项目: {Project}", projectPath);

            var arguments = new StringBuilder();
            arguments.Append($"pack \"{projectPath}\" ");
            arguments.Append($"-o \"{outputDirectory}\" ");

            if (!string.IsNullOrEmpty(version))
            {
                arguments.Append($"-p:Version={version} ");
            }

            if (properties != null)
            {
                foreach (var (key, value) in properties)
                {
                    arguments.Append($"-p:{key}={value} ");
                }
            }

            arguments.Append("--configuration Release");

            var result = await ExecuteDotNetCommandAsync(arguments.ToString(), Path.GetDirectoryName(projectPath)!);

            if (result.ExitCode == 0)
            {
                // 查找生成的包
                var packageFiles = Directory.GetFiles(outputDirectory, "*.nupkg");
                var latestPackage = packageFiles.OrderByDescending(File.GetCreationTime).FirstOrDefault();

                if (latestPackage != null)
                {
                    _logger.LogInformation("打包成功: {Package}", latestPackage);
                    return (true, latestPackage);
                }
                else
                {
                    _logger.LogWarning("打包完成但未找到包文件");
                    return (false, null);
                }
            }
            else
            {
                _logger.LogError("打包失败: {Output}", result.Output);
                return (false, null);
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "打包项目失败");
            return (false, null);
        }
    }

    /// <summary>
    /// 执行 NuGet 命令
    /// </summary>
    private async Task<(int ExitCode, string Output)> ExecuteNuGetCommandAsync(string arguments)
    {
        var startInfo = new ProcessStartInfo
        {
            FileName = "nuget",
            Arguments = arguments,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        return await ExecuteProcessAsync(startInfo);
    }

    /// <summary>
    /// 执行 dotnet 命令
    /// </summary>
    private async Task<(int ExitCode, string Output)> ExecuteDotNetCommandAsync(
        string arguments,
        string workingDirectory)
    {
        var startInfo = new ProcessStartInfo
        {
            FileName = "dotnet",
            Arguments = arguments,
            WorkingDirectory = workingDirectory,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        return await ExecuteProcessAsync(startInfo);
    }

    /// <summary>
    /// 执行进程
    /// </summary>
    private async Task<(int ExitCode, string Output)> ExecuteProcessAsync(ProcessStartInfo startInfo)
    {
        var output = new StringBuilder();

        using var process = new Process { StartInfo = startInfo };

        process.OutputDataReceived += (sender, e) =>
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                output.AppendLine(e.Data);
                _logger.LogDebug("{Line}", e.Data);
            }
        };

        process.ErrorDataReceived += (sender, e) =>
        {
            if (!string.IsNullOrEmpty(e.Data))
            {
                output.AppendLine(e.Data);
                _logger.LogWarning("Error: {Line}", e.Data);
            }
        };

        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        await process.WaitForExitAsync();

        return (process.ExitCode, output.ToString());
    }

    /// <summary>
    /// 添加 NuGet 源
    /// </summary>
    public async Task<bool> AddSourceAsync(string name, string source, string? username = null, string? password = null)
    {
        try
        {
            _logger.LogInformation("添加 NuGet 源: {Name} - {Source}", name, source);

            var arguments = $"sources add -Name \"{name}\" -Source \"{source}\"";

            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                arguments += $" -Username \"{username}\" -Password \"{password}\"";
            }

            var result = await ExecuteNuGetCommandAsync(arguments);

            return result.ExitCode == 0;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "添加 NuGet 源失败");
            return false;
        }
    }
}
